home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / shells / bashsrc.zoo / shell.c < prev    next >
C/C++ Source or Header  |  1991-06-05  |  26KB  |  1,033 lines

  1. /* shell.c -- GNU's idea of the POSIX shell specification.
  2.    Hopefully, this shell will contain significant enhancements.
  3.  
  4.    This file is part of Bash, the Bourne Again SHell.
  5.    Bash is free software; no one can prevent you from reading the source
  6.    code, or giving it to someone else.
  7.    This file is copyrighted under the GNU General Public License, which
  8.    can be found in the file called COPYING.
  9.  
  10.    Copyright (C) 1989 Free Software Foundation, Inc.
  11.  
  12.    This file is part of GNU Bash.
  13.  
  14.    Bash is distributed in the hope that it will be useful, but
  15.    WITHOUT ANY WARRANTY.  No author or distributor accepts
  16.    responsibility to anyone for the consequences of using it or for
  17.    whether it serves any particular purpose or works at all, unless he
  18.    says so in writing.  Refer to the GNU Emacs General Public License
  19.    for full details.
  20.  
  21.    Everyone is granted permission to copy, modify and redistribute
  22.    Bash, but only under the conditions described in the GNU General Public
  23.    License.   A copy of this license is supposed to have been given to you
  24.    along with GNU Emacs so you can know your rights and responsibilities.
  25.    It should be in a file named COPYING.
  26.  
  27.    Among other things, the copyright notice and this notice must be
  28.    preserved on all copies.
  29.  
  30.   Modification history:
  31.  
  32.   Sunday, January 10th, 1988.
  33.   Initial author: Brian Fox
  34.  
  35. */
  36.  
  37. #include <stdio.h>
  38. #include <signal.h>
  39. #include <errno.h>
  40. #include <sys/types.h>
  41. #ifndef SONY
  42. #include <fcntl.h>
  43. #endif
  44. #include <sys/file.h>
  45. #include <sys/stat.h>
  46. #include <pwd.h>
  47.  
  48. #if defined (HAVE_VPRINTF)
  49. #include <varargs.h>
  50. #endif
  51.  
  52. #include "shell.h"
  53. #include "flags.h"
  54.  
  55. #ifdef SYSV
  56. struct passwd *getpwuid();
  57. #endif
  58.  
  59. extern char *dist_version;
  60. extern int build_version;
  61.  
  62. extern int yydebug;
  63.  
  64. /* Non-zero means that this shell has already been run; i.e. you should
  65.    call shell_reinitialize () if you need to start afresh. */
  66. int shell_initialized = 0;
  67.  
  68. /* The current maintainer of the shell.  You change this in the
  69.    Makefile. */
  70. #ifndef MAINTAINER
  71. #define MAINTAINER "deliberately-anonymous"
  72. #endif
  73. char *the_current_maintainer = MAINTAINER;
  74.  
  75. #ifndef PPROMPT
  76. #define PPROMPT "bash\\$ "
  77. #endif
  78. char *primary_prompt = PPROMPT;
  79.  
  80. #ifndef SPROMPT
  81. #define SPROMPT "bash> "
  82. #endif
  83. char *secondary_prompt = SPROMPT;
  84.  
  85. COMMAND *global_command = (COMMAND *)NULL;
  86.  
  87. /* Non-zero after SIGINT. */
  88. int interrupt_state = 0;
  89.  
  90. /* The current user's name. */
  91. char *current_user_name = (char *)NULL;
  92.  
  93. /* The current host's name. */
  94. char *current_host_name = (char *)NULL;
  95.  
  96. /* Non-zero means that this shell is a login shell.
  97.    Specifically:
  98.    0 = not login shell.
  99.    1 = login shell from getty (or equivalent fake out)
  100.   -1 = login shell from "-login" flag.
  101.   -2 = both from getty, and from flag.
  102.  */
  103. int login_shell = 0;
  104.  
  105. /* Non-zero means this shell is running interactively. */
  106. int interactive = 0;
  107.  
  108. /* Non-zero means to remember lines typed to the shell on the history
  109.    list.  This is different than the user-controlled behaviour; this
  110.    becomes zero when we read lines from a file, for example. */
  111. int remember_on_history = 1;
  112.  
  113. /* Non-zero means this shell is restricted. */
  114. int restricted = 0;
  115.  
  116. /* Special debugging helper. */
  117. int debugging_login_shell = 0;
  118.  
  119. /* The environment that the shell passes to other commands. */
  120. char **shell_environment;
  121.  
  122. /* Non-zero when we are executing a top-level command. */
  123. int executing = 0;
  124.  
  125. /* The number of commands executed so far. */
  126. int current_command_number = 1;
  127.  
  128. /* The environment at the top-level REP loop.  We use this in the case of
  129.    error return. */
  130. jmp_buf top_level, catch;
  131.  
  132. /* Non-zero is the recursion depth for commands. */
  133. int indirection_level = 0;
  134.  
  135. /* The number of times BASH has been executed.  This is set
  136.    by initialize_variables () in variables.c. */
  137. int shell_level = 0;
  138.  
  139. /* The name of this shell, as taken from argv[0]. */
  140. char *shell_name;
  141.  
  142. /* The name of the .(shell)rc file. */
  143. char *bashrc_file = "~/.bashrc";
  144.  
  145. /* Non-zero means to act more like the Bourne shell on startup. */
  146. int act_like_sh = 0;
  147.  
  148. /* Values for the long-winded argument names. */
  149. int debugging = 0;        /* Do debugging things. */
  150. int no_rc = 0;            /* Don't execute ~/.bashrc */
  151. int no_profile = 0;        /* Don't execute .profile */
  152. int do_version = 0;        /* Display interesting version info. */
  153. int quiet = 0;            /* Be quiet when starting up. */
  154. int make_login_shell = 0;    /* Make this shell be a `-bash' shell. */
  155. int no_line_editing = 0;    /* Don't do fancy line editing. */
  156. int no_brace_expansion = 0;    /* Non-zero means no foo{a,b} -> fooa fooa. */
  157.  
  158. /* Some long-winded argument names.  These are obviously new. */
  159. #define Int 1
  160. #define Charp 2
  161. struct {
  162.   char *name;
  163.   int *value;
  164.   int type;
  165. } long_args[] = {
  166.   { "debug", &debugging, Int },
  167.   { "norc", &no_rc, Int },
  168.   { "noprofile", &no_profile, Int },
  169.   { "rcfile", (int *)&bashrc_file, Charp},
  170.   { "version", &do_version, Int},
  171.   { "quiet", &quiet, Int},
  172.   { "login", &make_login_shell, Int},
  173.   { "nolineediting", &no_line_editing, Int},
  174.   { "nobraceexpansion", &no_brace_expansion, Int},
  175.   { (char *)NULL, (int *)0x0, 0 }
  176. };
  177.  
  178. main (argc, argv, env)
  179.      int argc;
  180.      char **argv, **env;
  181. {
  182.   int i, arg_index = 1;
  183.   extern int yydebug;
  184.   FILE *default_input = stdin;
  185.   char *local_pending_command = (char *)NULL;
  186.   extern int last_command_exit_value;
  187.   int locally_skip_execution = 0, top_level_arg_index;
  188.   extern char *base_pathname ();
  189. #ifdef JOB_CONTROL
  190.   extern int job_control;
  191. #endif
  192.  
  193.   /* Wait forever if we are debugging a login shell. */
  194.   while (debugging_login_shell);
  195.       
  196.   /* If this shell has already been run, then reinitialize it to a
  197.      vanilla state. */
  198.   if (shell_initialized)
  199.     {
  200.       shell_reinitialize ();
  201.       if (setjmp (top_level))
  202.     exit (2);
  203.     }
  204.  
  205.   /* Here's a hack.  If the name of this shell is "sh", then don't do
  206.      any startup files; just try to be more like /bin/sh. */
  207.   {
  208.     char *tshell_name = base_pathname (argv[0]);
  209.  
  210.     if (*tshell_name == '-')
  211.       tshell_name++;
  212.  
  213.     if (strcmp (tshell_name, "sh") == 0)
  214.       act_like_sh++;
  215.   }
  216.  
  217.   yydebug = 0;
  218.  
  219.   shell_environment = env;
  220.   shell_name = argv[0];
  221.   if (*shell_name == '-')
  222.     {
  223.       shell_name++;
  224.       login_shell++;
  225.     }
  226.  
  227. #ifdef JOB_CONTROL
  228.   if (act_like_sh)
  229.     job_control = 0;
  230. #endif
  231.  
  232.   dollar_vars[0] = savestring (argv[0]);
  233.  
  234.   /* Parse argument flags from the input line. */
  235.  
  236.   /* Find full word arguments first. */
  237.   while ((arg_index != argc) && *(argv[arg_index]) == '-')
  238.     {
  239.       for (i = 0; long_args[i].name; i++)
  240.     {
  241.       if (strcmp (&(argv[arg_index][1]), long_args[i].name) == 0)
  242.         {
  243.           if (long_args[i].type == Int)
  244.         *(long_args[i].value) = 1;
  245.           else
  246.         {
  247.           if (!argv[++arg_index])
  248.             {
  249.               report_error ("%s: Flag `%s' expected an argument",
  250.                     shell_name, long_args[i].name);
  251.               exit (1);
  252.             }
  253.           else
  254.             *long_args[i].value = (int)argv[arg_index];
  255.         }
  256.           goto next_arg;
  257.         }
  258.     }
  259.       break;            /* No such argument.  Maybe flag arg. */
  260.     next_arg:
  261.       arg_index++;
  262.     }
  263.  
  264.   /* If user supplied the "-login" flag, then set and invert LOGIN_SHELL. */
  265.   if (make_login_shell)
  266.     login_shell = -++login_shell;
  267.  
  268.   /* All done with full word args; do standard shell arg parsing.*/
  269.   while (arg_index != argc && argv[arg_index] &&
  270.      (*(argv[arg_index]) == '-' || (*argv[arg_index] == '+')))
  271.     {
  272.       /* There are flag arguments, so parse them. */
  273.       int arg_character;
  274.       int on_or_off = (*argv[arg_index]);
  275.       int  i = 1;
  276.  
  277.       while (arg_character = (argv[arg_index])[i++])
  278.     {
  279.       switch (arg_character)
  280.         {
  281.         case 'c':
  282.           /* The next arg is a command to execute, and the following args
  283.          are $1 .. $n respectively. */
  284.           local_pending_command = argv[++arg_index];
  285.           if (!local_pending_command)
  286.         {
  287.           report_error ("`%cc' requires an argument", on_or_off);
  288.           exit (1);
  289.         }
  290.  
  291.           arg_index++;
  292.           goto after_flags;
  293.           break